package com.panfeng.xcloud.common.security.utils;

import com.panfeng.xcloud.common.core.utils.SpringContextUtil;
import com.panfeng.xcloud.common.security.annotation.NotNeedAccess;
import com.panfeng.xcloud.common.security.vo.NotNeedAccessMappingInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 *
 * 获取被忽略的不需要的鉴权url api资源
 *
 * @author xiaobo
 * @version 1.0
 * @since 2018-12-28
 */
@Slf4j
public class IgnoreUrlMatcher {

    /**
     * 获取不需要被忽略的鉴权url
     *
     * @return
     */
    public static List<NotNeedAccessMappingInfo> getIgnoreUrlsInfo(){
        //@TODO:当期服务有多个RequestMappingHandlerMapping对象，需要获取特定enpoint下的对象，上下文中有这些RequestMappingHandlerMapping：swagger2ControllerMapping,requestMappingHandlerMapping,oauth2EndpointHandlerMapping,endpointHandlerMapping
        RequestMappingHandlerMapping rmhp = SpringContextUtil.getApplicationContext().getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = rmhp.getHandlerMethods();
        List<NotNeedAccessMappingInfo> notNeedAccessMappingInfos = new ArrayList<NotNeedAccessMappingInfo>();
        for(RequestMappingInfo requestMappingInfo : map.keySet()){
            HandlerMethod handlerMethod = map.get(requestMappingInfo);
            Method method = handlerMethod.getMethod();
            NotNeedAccess notNeedAccess = AnnotationUtils.findAnnotation(method, NotNeedAccess.class);
            if(null != notNeedAccess){
                Object o = map.get(requestMappingInfo).getBean();
                PatternsRequestCondition p = requestMappingInfo.getPatternsCondition();
                Set<String> patterns = p.getPatterns();
                if(null != patterns && !patterns.isEmpty()){
                    List<String> patternsList = new ArrayList<String>(patterns);
                    for (String patternMappingUrl : patternsList) {
                        NotNeedAccessMappingInfo notNeedAccessMappingInfo = new NotNeedAccessMappingInfo();

                        notNeedAccessMappingInfo.setBeanObject(o);
                        notNeedAccessMappingInfo.setBeanName(o.toString());
                        notNeedAccessMappingInfo.setMethod(method);
                        notNeedAccessMappingInfo.setPatternMappingUrl(patternMappingUrl);

                        notNeedAccessMappingInfos.add(notNeedAccessMappingInfo);
                        log.info(">>>> 映射不需要鉴权的url信息：{}",notNeedAccessMappingInfo.toString());
                    }
                }
            }
        }
        return notNeedAccessMappingInfos;
    }

    /**
     * 获取不需要被忽略的鉴权url
     *
     * @return
     */
    public static List<String> getIgnoreUrls(){
        List<NotNeedAccessMappingInfo> ignoreUrlsInfos = getIgnoreUrlsInfo();
        List<String> ignoreUrls = new ArrayList<String>();
        for (NotNeedAccessMappingInfo ignoreUrlsInfo:ignoreUrlsInfos) {
            ignoreUrls.add(ignoreUrlsInfo.getPatternMappingUrl());
        }
        return ignoreUrls;
    }
}
